import shutil, os, stat, hashlib, time
from support.ui.console import Log
from typing import (
    IO,
    TYPE_CHECKING,
    Any,
    Callable,
    Dict,
    Iterable,
    List,
    Mapping,
    NamedTuple,
    Optional,
    TextIO,
    Tuple,
    Type,
    Union,
    cast,
)

class MediaFile(object):
    TAG = "MediaFile"

    TYPE_VIDEO_FILE = ['.mp4','.mov','.avi','.mkv','.rmvb','.3gp','.m4v','.flv']
    KB = 1024
    
    def __init__(self, task=None):
        self.task = task

    def calHash(self, path):
        hashm = hashlib.md5()
        fp = open(path, 'rb')
        while(True):
            data = fp.read(4 * self.KB)
            if(not data):
                break
            hashm.update(data)
        fp.close()
        return hashm.hexdigest()

    def getCreateDate(self, path):
        return time.strftime('%Y:%m:%d %H:%M:%S', time.localtime(os.path.getctime(path)))

    def copy(self, src, dst, taskid=0):
        Log.i(MediaFile.TAG, "from {} to {} copy start notify: {}:{}".format(src, dst, self.task, taskid))
        self.createPathIfNotExists(dst)
        if os.path.isdir(dst):
            dst = os.path.join(dst, os.path.basename(src))
        dst=self.__copyfile(src, dst, taskid=taskid)
        shutil.copystat(src, dst)
        Log.i(MediaFile.TAG, "from {} to {} copy end".format(src, dst))
        return 0 

        
    def move(self, src, dst):
        shutil.move(src, dst)
    
    def isVideo(self, src):
        return os.path.splitext(src)[-1].lower() in self.TYPE_VIDEO_FILE

    def createPathIfNotExists(self, path):
        if(not os.path.exists(path)):
            os.makedirs(path)

    def getSize(self, path):
        return os.path.getsize(path)

    def __copyfile(self, src, dst, *, follow_symlinks=True, taskid=None):
        if shutil._samefile(src, dst):
            Log.e(MediaFile.TAG, "{!r} and {!r} are the same file".format(src, dst))
            raise SameFileError("{!r} and {!r} are the same file".format(src, dst))
        for fn in [src, dst]:
            try:
                st = os.stat(fn)
            except OSError:
                pass
            else:
                if stat.S_ISFIFO(st.st_mode):
                    Log.e(MediaFile.TAG, "`%s` is a named pipe" % fn)
                    raise SpecialFileError("`%s` is a named pipe" % fn)

        if not follow_symlinks and os.path.islink(src):
            os.symlink(os.readlink(src), dst)
        else:
#            with open(src, 'rb') as fsrc:
#                with open(dst, 'wb') as fdst:
#                    self.__copyfileobj(fsrc, fdst, taskid=taskid)
            try:
                shutil.copy2(src, dst)
            except IOError as e:
                Log.e(MediaFile.TAG, "copy {} to {} failed".format(src, dst))

        return dst

    def __copyfileobj(self, fsrc, fdst, *, taskid, length=16*1024):
        while True:
            buf = fsrc.read(length)
            if not buf:
                break
            fdst.write(buf)
            if(self.task):
                self.task.updateProgressProcess(taskid, len(buf))

